/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-08-03 17:22:31
 * @LastEditTime: 2021-08-11 09:47:27
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#ifndef DRIVERS_FPCIE_COMMON_H
#define DRIVERS_FPCIE_COMMON_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "f_pcie_hw.h"
#include "kernel.h"

    /******************** Macros (Inline Functions) Definitions *******************/

/* each bus required 1 MB ecam space */
#define GET_MAX_BUS_NO(ecam_sz) (((ecam_sz) / (1024 * 1024)) - 1)

#define BITSPERLONG 64

/* Command register offsets */

/* Memory access enable */
#define FPCIE_CFG_CMD_MEM_EN 0x00000002

/* Bus master enable */
#define FPCIE_CFG_CMD_BUSM_EN 0x00000004

/* PCIe Configuration registers offsets */

/* Vendor ID/Device ID offset */
#define FPCIE_CFG_ID_REG 0x0000

/* Command/Status Register Offset */
#define FPCIE_CFG_CMD_STATUS_REG 0x0001

/* Primary/Sec.Bus Register Offset */
#define FPCIE_CFG_PRI_SEC_BUS_REG 0x0006

/* Cache Line/Latency Timer / Header Type / BIST Register Offset */
#define FPCIE_CFG_CAH_LAT_HD_REG 0x0003

#define FPCIE_CFG_BAR_MEM_TYPE_MASK 0x1 /* Memory or IO request */

#define FPCIE_CFG_BAR_MEM_AS_MASK 0x6 /* 32b or 64b address space */

/* PCIe Base Addr */
#define FPCIE_CFG_BAR_BASE_OFFSET 0x0004

/* PCIe Base Addr 0 */
#define FPCIE_CFG_BAR_0_REG 0x0004

/* PCIe Base Addr 1 */
#define FPCIE_CFG_BAR_1_REG 0x0005

/* PCIe Base Addr 2 */
#define FPCIE_CFG_BAR_2_REG 0x0006

/* PCIe Base Addr 3 */
#define FPCIE_CFG_BAR_3_REG 0x0007

/* PCIe Base Addr 4 */
#define FPCIE_CFG_BAR_4_REG 0x0008

#define FPCIE_CFG_BUS_NUMS_T1_REG 0X0006
#define FPCIE_CFG_NP_MEM_T1_REG 0X0008
#define FPCIE_CFG_P_MEM_T1_REG 0X0009
#define FPCIE_CFG_P_UPPER_MEM_T1_REG 0X000A
#define FPCIE_CFG_P_LIMIT_MEM_T1_REG 0X000B

#define FPCIE_CFG_FUN_NOT_IMP_MASK 0xFFFF
#define FPCIE_CFG_HEADER_TYPE_MASK 0x007F0000
#define FPCIE_CFG_MUL_FUN_DEV_MASK 0x00800000

#define FPCIE_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
#define FPCIE_BASE_ADDRESS_SPACE_IO 0x01
#define FPCIE_BASE_ADDRESS_SPACE_MEMORY 0x00
#define FPCIE_BASE_ADDRESS_MEM_TYPE_MASK 0x06
#define FPCIE_BASE_ADDRESS_MEM_TYPE_32 0x00  /* 32 bit address */
#define FPCIE_BASE_ADDRESS_MEM_TYPE_1M 0x02  /* Below 1M [obsolete] */
#define FPCIE_BASE_ADDRESS_MEM_TYPE_64 0x04  /* 64 bit address */
#define FPCIE_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
#define FPCIE_BASE_ADDRESS_MEM_MASK (~0x0fUL)
#define FPCIE_BASE_ADDRESS_IO_MASK (~0x03UL)

#define FPCIE_EP_MIN_APERTURE 128

/* BAR control values applicable to both Endpoint Function and Root Complex */
#define FPCIE_LM_BAR_CFG_CTRL_DISABLED 0x0
#define FPCIE_LM_BAR_CFG_CTRL_IO_32BITS 0x1
#define FPCIE_LM_BAR_CFG_CTRL_MEM_32BITS 0x4
#define FPCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS 0x5
#define FPCIE_LM_BAR_CFG_CTRL_MEM_64BITS 0x6
#define FPCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS 0x7

/*
 * Address Translation Registers
 */
#define FPCIE_AT_BASE FPCIE_REG_OUTBOUND_R0_PATR0_OFFSET
/*
 * Local Management Registers
 */
#define FPCIE_LM_BASE 0x2000

#define FPCIE_CFG_HEADER_O_TYPE 0x0000

/* Endpoint Function BAR Inbound PCIe to AXI Address Translation Register */
#define FPCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
    (FPCIE_AT_BASE + 0x0840 + (fn)*0x0040 + (bar)*0x0008)
#define FPCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
    (FPCIE_AT_BASE + 0x0844 + (fn)*0x0040 + (bar)*0x0008)

/* Endpoint Function f BAR b Configuration Registers */
#define FPCIE_LM_EP_FUNC_BAR_CFG0(fn) \
    (FPCIE_LM_BASE + 0x0240 + (fn)*0x0008)
#define FPCIE_LM_EP_FUNC_BAR_CFG1(fn) \
    (FPCIE_LM_BASE + 0x0244 + (fn)*0x0008)

#define FPCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) \
    (GENMASK(4, 0) << ((b)*8))
#define FPCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE(b, a) \
    (((a) << ((b)*8)) & FPCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b))
#define FPCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b) \
    (GENMASK(7, 5) << ((b)*8))
#define FPCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, c) \
    (((c) << ((b)*8 + 5)) & FPCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b))

#define FPCIE_REG_EP_C0_PREF_BASE_LIMIT_OFFSET_GET(config_addr, peu_num) \
    (u32)(config_addr + FPCIE_REG_EP_C0_PREF_BASE_LIMIT_OFFSET + ((peu_num + 3) % 3) * 16)

#define FPCIE_REG_EP_C0_MEM_BASE_LIMIT_OFFSET_GET(config_addr, peu_num) \
    (u32)(config_addr + FPCIE_REG_EP_C0_MEM_BASE_LIMIT_OFFSET + ((peu_num + 3) % 3) * 16)

#define FPCIE_BAR_MEM_TYPE_64 1
#define FPCIE_BAR_MEM_TYPE_32 0
#define FPCIE_PRIMARY_BUS 0x18

#define MB_SHIFT 20
#define HEX_NIBBLE 4
#define TWO_HEX_NIBBLES 8
#define FOUR_HEX_NIBBLES 16
#define EIGHT_HEX_NIBBLES 32

#ifdef __cplusplus
}
#endif

#endif // !
